import os
import sys
import winreg
import shutil
import subprocess
import threading
import tkinter as tk
from tkinter import messagebox
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from ttkbootstrap.scrolled import ScrolledText

def check_typora_installation():
    """检查当前电脑是否安装了Typora软件"""
    # 方法1: 检查注册表
    try:
        # 尝试打开Typora的注册表项
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Typora.exe")
        typora_path = winreg.QueryValue(key, None)  # 获取默认值，通常是程序路径
        winreg.CloseKey(key)
        return True, typora_path
    except FileNotFoundError:
        # 注册表中没有找到
        pass
    except Exception as e:
        print(f"检查注册表时出错: {e}")
    
    # 方法2: 检查常见安装路径
    common_paths = [
        os.path.join(os.environ.get('ProgramFiles', 'C:\\Program Files'), 'Typora', 'Typora.exe'),
        os.path.join(os.environ.get('ProgramFiles(x86)', 'C:\\Program Files (x86)'), 'Typora', 'Typora.exe'),
        os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Typora', 'Typora.exe')
    ]
    
    for path in common_paths:
        if os.path.isfile(path):
            return True, path
    
    # 方法3: 在PATH环境变量中查找
    for path_dir in os.environ.get('PATH', '').split(';'):
        typora_path = os.path.join(path_dir, 'Typora.exe')
        if os.path.isfile(typora_path):
            return True, typora_path
    
    return False, None

def copy_files_to_typora(typora_path, callback=None):
    """复制文件到Typora安装目录"""
    try:
        # 获取Typora安装目录
        typora_dir = os.path.dirname(typora_path)
        
        # 获取当前脚本所在目录
        current_dir = os.path.dirname(os.path.abspath(__file__))
        
        # 要复制的文件
        files_to_copy = [
            "node_inject.exe",
            "license-gen.exe"
        ]
        
        # 检查是否所有文件都已存在
        all_files_exist = True
        existing_files = []
        missing_source_files = []
        
        for file in files_to_copy:
            source_path = os.path.join(current_dir, file)
            target_path = os.path.join(typora_dir, file)
            
            if os.path.exists(target_path):
                existing_files.append(file)
                if callback:
                    callback(f"文件 {file} 已存在于 {typora_dir}")
            elif not os.path.exists(source_path):
                missing_source_files.append(file)
                if callback:
                    callback(f"错误: 找不到源文件 {source_path}")
        
        # 如果有源文件缺失，返回失败
        if missing_source_files:
            return False, {
                "status": "missing_source",
                "missing_files": missing_source_files
            }
        
        # 如果所有文件都已存在，则返回成功但不复制
        if len(existing_files) == len(files_to_copy):
            if callback:
                callback("所有文件已存在于Typora目录，无需复制")
            return True, {
                "status": "all_exist",
                "existing_files": existing_files
            }
        
        # 复制不存在的文件
        copied_files = []
        for file in files_to_copy:
            source_path = os.path.join(current_dir, file)
            target_path = os.path.join(typora_dir, file)
            
            if not os.path.exists(target_path) and os.path.exists(source_path):
                shutil.copy2(source_path, target_path)
                copied_files.append(file)
                if callback:
                    callback(f"已成功复制 {file} 到 {typora_dir}")
        
        return True, {
            "status": "partial_copy",
            "existing_files": existing_files,
            "copied_files": copied_files
        }
    except Exception as e:
        if callback:
            callback(f"复制文件时出错: {str(e)}")
        return False, {
            "status": "error",
            "error_message": str(e)
        }

def run_executables(typora_path, callback=None):
    """在Typora目录下运行可执行文件"""
    try:
        # 获取Typora安装目录
        typora_dir = os.path.dirname(typora_path)
        
        # 要运行的文件
        executables = [
            "node_inject.exe",
            "license-gen.exe"
        ]
        
        results = {}
        
        # 运行可执行文件
        for exe in executables:
            exe_path = os.path.join(typora_dir, exe)
            
            if os.path.exists(exe_path):
                if callback:
                    callback(f"正在运行 {exe}...")
                
                # 运行可执行文件并捕获输出
                process = subprocess.Popen(
                    exe_path, 
                    stdout=subprocess.PIPE, 
                    stderr=subprocess.PIPE,
                    cwd=typora_dir,
                    shell=True,
                    text=True
                )
                
                stdout, stderr = process.communicate()
                
                if process.returncode == 0:
                    results[exe] = stdout
                    if callback:
                        callback(f"{exe} 运行成功")
                else:
                    results[exe] = stderr
                    if callback:
                        callback(f"{exe} 运行失败: {stderr}")
            else:
                if callback:
                    callback(f"错误: 找不到可执行文件 {exe_path}")
        
        return results
    except Exception as e:
        if callback:
            callback(f"运行可执行文件时出错: {str(e)}")
        return {}

class TyporaCheckerApp(ttk.Window):
    def __init__(self):
        super().__init__(title="Typora工具箱", themename="cosmo", resizable=(True, True))
        self.geometry("700x500")
        self.minsize(600, 400)
        
        # 居中显示窗口
        self.center_window()
        
        # 创建变量
        self.typora_path = None
        self.is_processing = False
        self.process_thread = None
        
        # 创建界面
        self.create_widgets()
    
    def center_window(self):
        """将窗口居中显示"""
        self.update_idletasks()
        width = self.winfo_width()
        height = self.winfo_height()
        x = (self.winfo_screenwidth() // 2) - (width // 2)
        y = (self.winfo_screenheight() // 2) - (height // 2)
        self.geometry(f"{width}x{height}+{x}+{y}")
    
    def create_widgets(self):
        """创建GUI组件"""
        # 创建主框架
        main_frame = ttk.Frame(self, padding=15)
        main_frame.pack(fill=BOTH, expand=YES)
        
        # 顶部标题
        title_label = ttk.Label(
            main_frame, 
            text="Typora工具箱", 
            font=("Helvetica", 20, "bold"),
            bootstyle="primary"
        )
        title_label.pack(pady=10)
        
        # 描述标签
        desc_label = ttk.Label(
            main_frame,
            text="检查Typora安装并执行相关操作",
            font=("Helvetica", 10),
            bootstyle="secondary"
        )
        desc_label.pack(pady=(0, 15))
        
        # 按钮框架
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=X, pady=10)
        
        # 检查按钮
        self.check_button = ttk.Button(
            button_frame,
            text="检查Typora安装",
            command=self.check_typora,
            bootstyle="success-outline",
            width=18
        )
        self.check_button.pack(side=LEFT, padx=5)
        
        # 复制文件按钮
        self.copy_button = ttk.Button(
            button_frame,
            text="复制文件到Typora",
            command=self.copy_files,
            bootstyle="info-outline",
            width=18,
            state=DISABLED
        )
        self.copy_button.pack(side=LEFT, padx=5)
        
        # 运行可执行文件按钮
        self.run_button = ttk.Button(
            button_frame,
            text="运行可执行文件",
            command=self.run_exes,
            bootstyle="warning-outline",
            width=18,
            state=DISABLED
        )
        self.run_button.pack(side=LEFT, padx=5)
        
        # 状态框架
        status_frame = ttk.LabelFrame(main_frame, text="状态信息", padding=10)
        status_frame.pack(fill=X, pady=10)
        
        # 状态标签
        self.status_var = tk.StringVar()
        self.status_var.set("点击'检查Typora安装'按钮开始")
        
        status_label = ttk.Label(
            status_frame,
            textvariable=self.status_var,
            font=("Helvetica", 10),
            bootstyle="primary",
            wraplength=650
        )
        status_label.pack(fill=X, pady=5)
        
        # 进度条
        self.progress = ttk.Progressbar(
            status_frame,
            bootstyle="success-striped",
            mode="determinate",
            value=0
        )
        self.progress.pack(fill=X, pady=5)
        
        # 日志框架
        log_frame = ttk.LabelFrame(main_frame, text="操作日志", padding=10)
        log_frame.pack(fill=BOTH, expand=YES, pady=10)
        
        # 日志文本框
        self.log_text = ScrolledText(log_frame, height=10)
        self.log_text.pack(fill=BOTH, expand=YES)
    
    def update_progress(self, value, message=""):
        """更新进度条和状态信息"""
        self.progress["value"] = value
        if message:
            self.status_var.set(message)
            self.log(message)
    
    def log(self, message):
        """添加日志信息"""
        self.log_text.insert(tk.END, f"{message}\n")
        self.log_text.see(tk.END)  # 滚动到最新内容
    
    def check_typora(self):
        """检查Typora安装"""
        self.update_progress(0, "正在检查Typora安装...")
        installed, path = check_typora_installation()
        
        if installed:
            self.typora_path = path
            self.update_progress(100, f"✅ Typora已安装! 安装路径: {path}")
            self.copy_button["state"] = NORMAL
            messagebox.showinfo("检查结果", f"Typora已安装!\n安装路径: {path}")
        else:
            self.update_progress(100, "❌ 未检测到Typora安装。您可以从官网下载: https://typora.io/")
            self.copy_button["state"] = DISABLED
            self.run_button["state"] = DISABLED
            messagebox.showwarning("检查结果", "未检测到Typora安装。\n您可以从官网下载: https://typora.io/")
    
    def copy_files(self):
        """复制文件到Typora安装目录"""
        if not self.typora_path:
            self.update_progress(0, "请先检查Typora安装")
            return
        
        if self.is_processing:
            return
        
        self.is_processing = True
        self.update_progress(10, "准备复制文件...")
        self.check_button["state"] = DISABLED
        self.copy_button["state"] = DISABLED
        
        # 在新线程中执行复制操作
        def copy_thread():
            success, result_info = copy_files_to_typora(self.typora_path, self.update_progress_callback)
            
            # 在主线程中更新UI
            self.after(0, lambda: self.copy_completed(success, result_info))
        
        self.process_thread = threading.Thread(target=copy_thread)
        self.process_thread.daemon = True
        self.process_thread.start()
    
    def update_progress_callback(self, message):
        """线程安全的进度更新回调"""
        self.after(0, lambda: self.update_progress(50, message))
    
    def copy_completed(self, success, result_info=None):
        """复制完成后的回调"""
        self.is_processing = False
        self.check_button["state"] = NORMAL
        self.copy_button["state"] = NORMAL
        
        if success:
            self.update_progress(100, "✅ 操作完成!")
            self.run_button["state"] = NORMAL
            
            # 根据不同状态显示不同的提示信息
            if result_info and "status" in result_info:
                if result_info["status"] == "all_exist":
                    # 所有文件都已存在
                    existing_files = result_info.get("existing_files", [])
                    files_str = "\n- ".join([""] + existing_files)
                    messagebox.showinfo(
                        "文件已存在", 
                        f"以下文件已存在于Typora目录，无需复制:{files_str}\n\n您可以直接点击'执行文件'按钮。"
                    )
                elif result_info["status"] == "partial_copy":
                    # 部分文件已存在，部分文件被复制
                    existing_files = result_info.get("existing_files", [])
                    copied_files = result_info.get("copied_files", [])
                    
                    message = ""
                    if existing_files:
                        existing_str = "\n- ".join([""] + existing_files)
                        message += f"以下文件已存在于Typora目录:{existing_str}\n\n"
                    
                    if copied_files:
                        copied_str = "\n- ".join([""] + copied_files)
                        message += f"以下文件已复制到Typora目录:{copied_str}"
                    
                    messagebox.showinfo("复制结果", message)
                else:
                    messagebox.showinfo("复制结果", "文件已成功复制到Typora安装目录!")
            else:
                messagebox.showinfo("复制结果", "文件已成功复制到Typora安装目录!")
        else:
            self.update_progress(100, "❌ 文件复制失败!")
            
            # 显示详细的错误信息
            error_message = "文件复制失败，请检查日志信息!"
            if result_info and "status" in result_info:
                if result_info["status"] == "missing_source":
                    missing_files = result_info.get("missing_files", [])
                    files_str = "\n- ".join([""] + missing_files)
                    error_message = f"找不到以下源文件:{files_str}\n\n请确保这些文件存在于程序目录中。"
                elif result_info["status"] == "error" and "error_message" in result_info:
                    error_message = f"复制文件时出错: {result_info['error_message']}"
            
            messagebox.showerror("复制结果", error_message)
    
    def run_exes(self):
        """运行可执行文件"""
        if not self.typora_path:
            self.update_progress(0, "请先检查Typora安装")
            return
        
        if self.is_processing:
            return
        
        # 添加确认对话框
        confirm = messagebox.askyesno(
            "确认执行", 
            "确定要执行Typora目录下的node_inject.exe和license-gen.exe吗？",
            icon="question"
        )
        
        if not confirm:
            self.update_progress(0, "已取消执行操作")
            return
        
        self.is_processing = True
        self.update_progress(10, "准备运行可执行文件...")
        self.check_button["state"] = DISABLED
        self.copy_button["state"] = DISABLED
        self.run_button["state"] = DISABLED
        
        # 在新线程中执行运行操作
        def run_thread():
            results = run_executables(self.typora_path, self.update_progress_callback)
            
            # 在主线程中更新UI
            self.after(0, lambda: self.run_completed(results))
        
        self.process_thread = threading.Thread(target=run_thread)
        self.process_thread.daemon = True
        self.process_thread.start()
    
    def run_completed(self, results):
        """运行完成后的回调"""
        self.is_processing = False
        self.check_button["state"] = NORMAL
        self.copy_button["state"] = NORMAL
        self.run_button["state"] = NORMAL
        
        if results and "license-gen.exe" in results:
            license_output = results["license-gen.exe"]
            self.update_progress(100, "✅ 可执行文件运行完成!")
            
            # 提取许可证信息
            license_key = ""
            if "License for you:" in license_output:
                license_key = license_output.split("License for you:")[1].strip()
            
            self.log("\n--- license-gen.exe 输出 ---")
            self.log(license_output)
            
            # 创建许可证显示框架
            if not hasattr(self, 'license_frame'):
                self.license_frame = ttk.LabelFrame(self.log_text.master, text="许可证信息", padding=10)
                self.license_frame.pack(fill=X, pady=10, before=self.log_text)
                
                self.license_var = tk.StringVar()
                self.license_entry = ttk.Entry(
                    self.license_frame, 
                    textvariable=self.license_var,
                    font=("Consolas", 12),
                    bootstyle="success",
                    justify="center"
                )
                self.license_entry.pack(fill=X, pady=5, padx=5)
                
                copy_license_button = ttk.Button(
                    self.license_frame,
                    text="复制许可证",
                    command=self.copy_license,
                    bootstyle="info-outline",
                    width=15
                )
                copy_license_button.pack(pady=5)
                
                # 立即调整窗口大小以确保许可证框架显示
                self.update_idletasks()
                self.adjust_window_size()
            
            # 更新许可证信息
            self.license_var.set(license_key)
            
            # 显示成功消息
            messagebox.showinfo("运行结果", "可执行文件已成功运行!\n许可证已生成，可以直接复制使用。")
        else:
            self.update_progress(100, "❌ 可执行文件运行失败!")
            messagebox.showerror("运行结果", "可执行文件运行失败，请检查日志信息!")
    
    def copy_license(self):
        """复制许可证到剪贴板"""
        license_key = self.license_var.get()
        if license_key:
            self.clipboard_clear()
            self.clipboard_append(license_key)
            self.update_progress(100, "✅ 许可证已复制到剪贴板!")
            messagebox.showinfo("复制成功", "许可证已复制到剪贴板!")
        else:
            messagebox.showwarning("复制失败", "没有可用的许可证信息!")
    
    def adjust_window_size(self):
        """调整窗口大小以确保所有内容都能显示"""
        # 更新窗口以获取当前所有组件的实际尺寸
        self.update_idletasks()
        
        # 获取当前窗口大小
        current_width = self.winfo_width()
        current_height = self.winfo_height()
        
        # 设置一个固定的增加高度，确保许可证框架能够完全显示
        # 许可证框架大约需要100-150像素的高度
        new_height = current_height + 150
        
        # 确保窗口不会超出屏幕
        screen_height = self.winfo_screenheight()
        if new_height > screen_height - 100:  # 保留一些边距
            new_height = screen_height - 100
        
        # 调整窗口大小
        self.geometry(f"{current_width}x{new_height}")
        
        # 重新居中窗口
        x = (self.winfo_screenwidth() // 2) - (current_width // 2)
        y = (self.winfo_screenheight() // 2) - (new_height // 2)
        
        # 确保窗口顶部不会超出屏幕
        if y < 0:
            y = 10
        
        self.geometry(f"{current_width}x{new_height}+{x}+{y}")

def main():
    # 命令行模式
    if len(sys.argv) > 1 and sys.argv[1] == "--cli":
        installed, path = check_typora_installation()
        if installed:
            print(f"Typora已安装! 安装路径: {path}")
            
            # 复制文件
            print("正在复制文件到Typora安装目录...")
            success, result_info = copy_files_to_typora(path, lambda msg: print(msg))
            
            if success:
                # 根据不同状态显示不同的提示信息
                if result_info and "status" in result_info:
                    if result_info["status"] == "all_exist":
                        # 所有文件都已存在
                        existing_files = result_info.get("existing_files", [])
                        print("\n以下文件已存在于Typora目录，无需复制:")
                        for file in existing_files:
                            print(f"- {file}")
                    elif result_info["status"] == "partial_copy":
                        # 部分文件已存在，部分文件被复制
                        existing_files = result_info.get("existing_files", [])
                        copied_files = result_info.get("copied_files", [])
                        
                        if existing_files:
                            print("\n以下文件已存在于Typora目录:")
                            for file in existing_files:
                                print(f"- {file}")
                        
                        if copied_files:
                            print("\n以下文件已复制到Typora目录:")
                            for file in copied_files:
                                print(f"- {file}")
                
                print("\n准备运行可执行文件...")
                # 运行可执行文件
                results = run_executables(path, lambda msg: print(msg))
                
                if results and "license-gen.exe" in results:
                    license_output = results["license-gen.exe"]
                    print("\n--- license-gen.exe 输出 ---")
                    print(license_output)
                    
                    # 提取并单独显示许可证
                    if "License for you:" in license_output:
                        license_key = license_output.split("License for you:")[1].strip()
                        print("\n" + "="*40)
                        print(f"您的许可证: {license_key}")
                        print("="*40)
                        print("(可直接复制使用)")
                else:
                    print("运行可执行文件失败!")
            else:
                # 显示详细的错误信息
                error_message = "文件复制失败!"
                if result_info and "status" in result_info:
                    if result_info["status"] == "missing_source":
                        missing_files = result_info.get("missing_files", [])
                        print("\n找不到以下源文件:")
                        for file in missing_files:
                            print(f"- {file}")
                        print("\n请确保这些文件存在于程序目录中。")
                    elif result_info["status"] == "error" and "error_message" in result_info:
                        print(f"\n复制文件时出错: {result_info['error_message']}")
                else:
                    print(error_message)
            
            return 0
        else:
            print("未检测到Typora安装。您可以从官网下载: https://typora.io/")
            return 1
    # GUI模式
    else:
        app = TyporaCheckerApp()
        app.mainloop()
        return 0

if __name__ == "__main__":
    sys.exit(main())